package com.xci.core.helper;

import cn.hutool.core.util.StrUtil;
import com.xci.core.base.PrimaryKeyValue;
import com.xci.core.internal.Const;
import com.xci.core.domain.TreeModel;
import com.xci.core.web.TreeNodeIndex;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 树形结构操作类
 * @author 吕艳阳
 */
public class TreeHelper {
    /**
     * 生成路径字符串
     * @param parentPath 上级路径
     * @param index 序号
     * @return 返回新创建的排序路径
     */
    public static String buildPath(String parentPath, Integer index) {
        if (Helper.isBlank(parentPath)) {
            parentPath = Const.EMPTY;
        }
        return parentPath + StrUtil.fillBefore(index.toString(), '0', Const.PATH_LENGTH);
    }

    /**
     * 获取新建节点排序路径
     * @param index 序号
     */
    public static String buildNewPath(Integer index) {
        return StrUtil.fillBefore(index.toString(), '0', Const.PATH_LENGTH);
    }

    /**
     * 树形查询条件
     * @param list 数据源
     * @param resultList 结果列表
     */
    public static List<?> filter(List<? extends TreeModel> list, List resultList) {
        // Predicate<? super TreeModel> predicate
        // List resultList = list.stream().filter(predicate).collect(Collectors.toList());
        if (resultList == null || resultList.size() == 0)
            return resultList;
        List<TreeModel> treeList = new ArrayList<>();
        for (Object entity : resultList) {
            TreeModel model = (TreeModel) entity;
            //先把自己加入进来
            treeList.add(model);
            //向上查询
            Long pid = model.getParentId();
            getParentsCore(list, treeList, pid);
        }
        //treeList.sort(Comparator.comparing(TreeModel::getPath));
        return treeList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 获取指定节点的所有父节点
     * @param list 数据源
     * @param id 指定节点id
     * @param hasSelf 是否包含自身
     */
    public static List<?> getParents(List<? extends TreeModel> list, Long id, boolean hasSelf) {
        TreeModel current = getCurrentModel(list, id);
        List<TreeModel> storeList = new ArrayList<>();
        if (current != null) {
            if (hasSelf) {
                storeList.add(current);
            }
            getParentsCore(list, storeList, current.getParentId());
        }
        return storeList;
    }

    private static void getParentsCore(List<? extends TreeModel> list, List<TreeModel> storeList, Long pid) {
        while (true) {
            if (pid <= 0)
                break;
            final Long parentId = pid;
            Optional<? extends TreeModel> parentOptional = list.stream().filter(p -> p.getId().equals(parentId)).findFirst();
            if (!parentOptional.isPresent())
                break;

            TreeModel parent = parentOptional.get();
            storeList.add(parent);
            pid = parent.getParentId();
        }
    }

    /**
     * 获取指定节点的所有子节点
     * @param list 数据源
     * @param id 指定节点id
     * @param hasSelf 是否包含自身
     */
    public static List<?> getChilds(List<? extends TreeModel> list, Long id, boolean hasSelf) {
        TreeModel current = getCurrentModel(list, id);
        List<TreeModel> storeList = new ArrayList<>();
        if (current != null) {
            if (hasSelf) {
                storeList.add(current);
            }
            getChildsCore(list, storeList, current.getId());
        }
        return storeList;
    }

    private static void getChildsCore(List<? extends TreeModel> entityList, List<TreeModel> storeList, Long id) {
        List<TreeModel> data = entityList.stream().filter(p -> p.getParentId().equals(id)).collect(Collectors.toList());
        if (data.size() <= 0)
            return;
        for (TreeModel item : data) {
            storeList.add(item);
            getChildsCore(entityList, storeList, item.getId());
        }
    }

    private static TreeModel getCurrentModel(List<? extends TreeModel> list, Long id) {
        Optional<? extends TreeModel> entityOptional = list.stream().filter(p -> p.getId().equals(id)).findFirst();
        return entityOptional.orElse(null);
    }

    /**
     * 转为键值对对象集合
     */
    public static List<PrimaryKeyValue> toPrimaryKeyValues(List<TreeNodeIndex> nodeIndexs){
        var list = new ArrayList<PrimaryKeyValue>();
        for (TreeNodeIndex nodeIndex : nodeIndexs) {
            list.add(new PrimaryKeyValue(nodeIndex.getId(),"ParentId",nodeIndex.getParentId()));
            list.add(new PrimaryKeyValue(nodeIndex.getId(),"Path",nodeIndex.getIndex().toString()));
        }
        return list;
    }
}